home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / EGAVGA.SWG / 0109_Rotate 256x256 bitmap.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  7KB  |  192 lines

  1. {$A+,B-,D+,E+,F-,G+,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V-,X+,Y+}
  2. {$M 16384,0,32786}
  3. Program BitMap;       { rotates/pans/scales a 256x256 bitmap }
  4. USES CRT;                 { by Paul H. Kahler   Jan 1994 }
  5.  
  6. Var   SinTable,CosTable: Array[0..255] of integer;
  7.       Sin2Table,Cos2Table: Array[0..255] of integer;
  8.       Map:word; {used as a pointer to the bitmap}
  9.  
  10. Procedure MakeTables;                   {Creates sin/cos tables}
  11. Var direction:integer;
  12.     angle:real;
  13. begin
  14.      For Direction:=0 to 255 do begin   {use 256 degrees in circle}
  15.          angle:=Direction;
  16.          angle:=angle*3.14159265/128;
  17.          SinTable[Direction]:=round(Sin(angle)*256);
  18.          CosTable[Direction]:=round(Cos(angle)*256);
  19.          Sin2Table[Direction]:=round(Sin(angle+3.14159265/2)*256*1.2);
  20.          Cos2Table[Direction]:=round(Cos(angle+3.14159265/2)*256*1.2);
  21.      end;                 { the 1.2 accounts for pixel aspect ratio }
  22. end;
  23.  
  24. Procedure DrawScreen(x,y,scale:word; rot:byte);
  25. var Temp:Longint;            {used for intermediate large values}
  26.     ddx,ddy,d2x,d2y:integer;
  27.     i,j:word;
  28.     label hloop,vloop,nodraw;
  29.  
  30. begin
  31. { the following 8 lines of code calculate a 'right' and 'down' vector used
  32.   for scanning the source bitmap. I use quotes because these directions
  33.   depend on the rotation. For example, with a rotation, 'right' could mean
  34.   up and to the left while 'down' means up and to the right. Since the
  35.   destination image (screen) is scanned left-right/top-bottom, the bitmap
  36.   needs to be scanned in arbitrary directions to get a rotation. }
  37.  
  38.      Temp:=(CosTable[rot]);Temp:=(Temp*Scale) div 256;
  39.      ddx:=Temp;
  40.      Temp:=(SinTable[rot]);Temp:=(Temp*Scale) div 256;
  41.      ddy:=Temp;
  42.  
  43. { Different tables are used for the 'down' vector to account for the non-
  44.   square pixels in mode 13h (320x200). The 90 degree difference is built
  45.   into the tables. If you don't like that, then use (rot+64)and255 here
  46.   and take the pi/2 out of CreateTables. To each his own I guess. }
  47.  
  48.      Temp:=(Cos2Table[rot]);Temp:=(Temp*SCALE) div 256;
  49.      d2x:=Temp;
  50.      Temp:=(Sin2Table[rot]);Temp:=(Temp*SCALE) div 256;
  51.      d2y:=Temp;
  52.  
  53. { Since we want to rotate around the CENTER of the screen and not the upper
  54.   left corner, we need to move 160 pixels 'left' and 100 'up' in the bitmap.}
  55.  
  56.      i:=x-ddx*160-d2x*100; j:=y-ddy*160-d2y*100;
  57.  
  58. { The following chunk of assembly does the good stuff. It redraws the entire
  59.   screen by scanning left-right/top-bottom on screen while also scanning the
  60.   bitmap in the arbitrary directions determined above. }
  61.  
  62.          ASM
  63.                  push ds
  64.                  mov  ax,[Map]      {get segment of bitmap}
  65.                  mov  ds,ax
  66.                  mov  ax,$a000      {set es: to video memory}
  67.                  mov  es,ax
  68.                  mov  ax,0          {set ds: to upper left corner of}
  69.                  mov  di,ax         {the video memory}
  70.                  mov  ax,[ddx]      {this is just to speed things up later}
  71.                  mov  si,ax         {add ax,si  faster than  add ax,[ddx] }
  72.                  mov  cx,200        {Number of rows on Screen}
  73.          vloop:
  74.                  push cx
  75.                  mov  ax,[i]        {start scanning the source bitmap}
  76.                  mov  dx,[j]        {at i,j which were calculated above.}
  77.                  mov  cx,320        {Number of coulumns on screen}
  78.          hloop:
  79.                  add  ax,si        {add the 'right' vector to the current}
  80.                  add  dx,[ddy]     {bitmap coordinates.  8.8 fixed point}
  81.                  mov  bl,ah        {  bx = 256*int(y)+int(x)  }
  82.                  mov  bh,dh
  83.                  mov  bl,[ds:bx]   { load a pixel from source }
  84.                  mov  [es:di],bl   { copy it to destination }
  85.                  inc  di           { advance to next destination pixel }
  86.  
  87.          {*** by repeating the above 7 instructions 5 times, and reducing
  88.               the loop count to 64, I have hit 37fps on a 486-33 with a
  89.               fast video card. ***}
  90.  
  91.                  loop hloop         {End of horizontal loop}
  92.  
  93.                  mov  ax,d2x        { get the 'down' vector }
  94.                  mov  dx,d2y
  95.  
  96.               { add  si,2 }    {** uncomment this instr. for extra fun **}
  97.  
  98.                  add  i,ax          { i,j is the starting coords for a line }
  99.                  add  j,dx          { so this moves down one line }
  100.                  pop  cx            { get the row count back and loop }
  101.                  loop vloop         { End of verticle loop }
  102.                  pop  ds            { Restore the ds }
  103.          end;
  104. end;
  105.  
  106. Procedure GraphMode;      {start 320x200x256 mode}
  107. begin
  108.      Asm
  109.         Mov     AH,00
  110.         Mov     AL,13h
  111.         Int     10h
  112.      end;
  113. end;
  114.  
  115. Procedure AllocateMem;  {returns a segment pointer for a 64K bitmap}
  116. label noerror;
  117. begin
  118.      asm
  119.               mov   ah,$48
  120.               mov   bx,$1000     { request 64K }
  121.               int   $21
  122.               jnc   noerror
  123.               mov   ax,0000
  124.      noerror: mov   Map,ax       { The segment pointer goes in Map }
  125.               end;
  126.      If Map=0 then begin
  127.         Writeln('Could not allocate enough memory');
  128.         Writeln('Program ending...');
  129.         Halt;end;
  130. end;
  131.  
  132. Procedure GiveBackMem; {returns the memory used for the map to the system}
  133. begin
  134.      asm
  135.         mov  ah,$49
  136.         mov  dx,Map
  137.         mov  es,dx
  138.         int  $21
  139.      end;
  140. end;
  141.  
  142. Procedure DrawImage;  {draws a test image which shows some limitations.}
  143.  
  144. { If anyone stuffs in code to load a picture in a standard format
  145.   (ie .gif .bmp etc..) I'd like if you send me a copy. Preferably
  146.   something simple. This will have to do for now. }
  147.  
  148. Var x,y:integer;
  149. Begin
  150.      for x:=-32768 to 32767 do mem[Map:x]:=0;
  151.      for y:=0 to 15 do          {this just frames the area}
  152.         for x:=y to 255 do begin
  153.            mem[Map:Y*256+x]:=1;
  154.            mem[Map:X*256+y]:=2;
  155.            end;
  156.      for y:=16 to 47 do         { this part show Aliasing effects }
  157.         for x:=16 to 255 do mem[Map:Y*256+x]:=2+(x and 1)+(y and 1);
  158.  
  159.      for y:= -50 to 50 do       { this draw the circles }
  160.         for x:= round(-sqrt(2500 - y*y)) to round(sqrt(2500 - y*y)) do
  161.           mem[Map:(y+100)*256+x+100]:=5+(X*X+Y*Y) div 100;
  162.  
  163.      for x:=0 to 100 do         { These lines also show sampling effects }
  164.         for y:=0 to 8 do
  165.            mem[Map:(Y*2560)+x+41100]:=5;
  166. end;
  167.  
  168. Var    rot,dr:word;
  169.        x,y,dist,dd:word;
  170.  
  171. Begin
  172.      AllocateMem;
  173.      DrawImage;
  174.      MakeTables;
  175.      GraphMode;
  176.      x:=32768; y:=0;         {this corresponds to (128,0) in fixed point}
  177.      rot:=0; dr:=1;          {rotation angle and it's delta}
  178.      dist:=1200; dd:=65534;  {distance to bitmap (sort of) and its delta}
  179.      repeat
  180.         DrawScreen(x,y,dist,lo(rot));
  181.         rot:=rot+dr;
  182.         y:=y+128;      {slow panning. 1/2 pixel per frame}
  183.         dist:=dist+dd;
  184.         if (dist=2000) or (dist=2) then dd:=-dd;
  185.         if random(150)=1 then dr:=random(7)-3;
  186.      until keypressed;
  187.      GiveBackMem;
  188.      ASM {back to 80x25}
  189.       MOV AX,3
  190.       INT 10h
  191.      END;
  192. end.